<?php
define( "COMMENT_OK",			0 );
define( "COMMENT_ACCESSDENIED",	1 );
define( "COMMENT_EMPTYBODY",	2 );
define( "COMMENT_DELETED",		3 );
define( "COMMENT_ERROR",		4 );

abstract class Handler_Comments extends RL_Handler
{
	/**
	 * Модель комментария, рекомендуется использовать ее, вместо получения новой
	 *
	 * @var Model_Comment
	 **/
	public $m_comment;

	/**
	 * Модель ленты древовидных комментариев
	 *
	 * @var Model_TreeComments
	 **/
	public $m_tc;

	public function getOneComment( $comment_oid ) {
		$comment = $this->m_comment->getOneCommentAsObject( $comment_oid );
		return $this->process_comment($comment);
	}

	/**
	 * Обновляет комментарий. Сохраняет edited информацию про юзера. Делает фильтрацию html.
	 *
	 * @return int - статус
	 * @author Alexander Sibiryakov
	 **/
	public function updateCommentSmart($comment_oid, $cbody, $user_id) {
		// найдем объект
		$comment = $this->m_comment->getOneCommentAsObject($comment_oid);

		$now = RL_CyrDate::newNow();
		$comment->data['edited_dtime'] = $now->format("%Y-%m-%d %H:%i:%s");
		$comment->data['edited_user_oid'] = $user_id;

		$cbody = $this->commentHtmlCleaner($cbody);

		$aa = &$this->aa;
		//$t = $aa->available_operations;
		$aa->getAvailableOperations($comment->id);
		$__s = $aa->is_granted(array('comment_edit'));
		//$aa->available_operations = $t;
		// 1. проверим права
		if	(!$__s) {
			return COMMENT_ACCESSDENIED;
		}

		// 2. проверим не пустое ли тело нам прислали

		if ( trim($cbody)=="" ) {
			return COMMENT_EMPTYBODY;
		}

		if ($comment->data['is_deleted']==1) {
			return COMMENT_DELETED;
		}

		// 3. пересохраняем, если все ок - вернем COMMENT_OK
		// если мы дошли до этого места, то поидее ошибок не должно возникнуть

		$comment->data['text'] = $cbody;
		$res = $comment->save();
		$res = $comment->updateSense( 'comment' );

		// получить автора записи
		$i = $this->ctx->mm->getModel("Item", "m");
		$item = $i->getItem($comment->data['item_oid']);

		// добавим событие об изменении коммента
		$m_oi = $this->ctx->mm->getModel("OpenId", "m");
		if (isset($item->data['posted_by_id'])) {
			$rs = $m_oi->get_openid_for_user_by_oid($item->data['posted_by_id']);
			while ($openid = $rs->next()) {
				$this->ctx->logger->event(new Event(time(), "edit_comment", $openid['openid'], $item->id));
			}

		}

		if ( $this->ctx->rh->use_search && $this->ctx->rh->search_in_comments ) {
			require_once 'includes/workaholic.php';
			Workaholic::addTask(array($this, 'hashItem'), $comment->id);
		}

		$this->ctx->logger->flushLog();

		return COMMENT_OK;


	}

	/**
	 * Делает сабмит от текущего пользователя. Внутри фильтрует html и рассчитывает уровень.
	 * Используется при ответе на комментарий.
	 *
	 * @return fobject или false
	 * @author Alexander Sibiryakov
	 **/
	public function submitCommentOnComment( $item_oid, $parent_oid, $cbody ) {
		$aa = &$this->aa;

		$offset = $aa->getCommentLevel( $item_oid, $parent_oid );

		if ($offset != 0) $offset++;

		return $this->submitComment($item_oid, $offset, $cbody, false);
	}

	/**
	 * Делает сабмит от текущего пользователя. Используется при комментировании итема.
	 *
	 * @return void
	 * @author Alexander Sibiryakov
	 **/
	public function submitCommentOnItem($item_oid, $cbody) {

		return $this->submitComment($item_oid, 1, $cbody, true);

	}

	public function deleteComment($comment_oid) {
		// 1. проверим права
		$aa = &$this->aa;
		$aa->getAvailableOperations($comment_oid);
		$__s = $aa->is_granted(array('comment_delete'));
		// 1. проверим права
		if	(!$__s) {
			return COMMENT_ACCESSDENIED;
		}

		// найдем объект
		$comment = $this->m_comment->getOneCommentAsObject($comment_oid);
		if ($comment) {
			$data = $this->ctx->store->getObject($comment->data['item_oid']);

			$this->m_comment->deleteCommentObject( $comment );

			// добавим событие об изменении коммента
			if (isset($comment->data['posted_by_id'])) {
				$m_oi = $this->ctx->mm->getModel("OpenId", "m");
				$rs = $m_oi->get_openid_for_user_by_oid($comment->data['posted_by_id']);
				while ($openid = $rs->next()) {
					$this->ctx->logger->event(new Event(time(), "delete_comment", $openid['openid'], $comment->id));
				}
			}

			if ( $this->ctx->rh->use_search && $this->ctx->rh->search_in_comments ) {
				require_once 'includes/workaholic.php';
				Workaholic::addTask(array($this, 'deleteItem'), $comment->id);
			}

			$this->ctx->logger->flushLog();
			return COMMENT_OK;
		} else {
			return COMMENT_ERROR;
		}

	}


	private function submitComment($item_oid, $offset, $cbody, $is_on_item) {
		$posted_by_oid = $this->aa->acl_data['user_id'] ? $this->aa->acl_data['user_id']:"0";

		$obj = $this->m_comment->submitComment( $this->commentHtmlCleaner($cbody), $item_oid, $posted_by_oid, $offset);

		if ($obj instanceof fobject)  {

			// добавим событие о создании комента
			$m_oi = $this->ctx->mm->getModel("OpenId", "m");
			if (isset($this->aa->acl_data['user_id'])) {
				$rs = $m_oi->get_openid_for_user_by_oid($this->aa->acl_data['user_id']);
				if ($rs)
				while ($openid = $rs->next()) {
					// владелец автор комментария
					$this->ctx->logger->event(new Event(time(), "create_comment", $openid['openid'], $obj->id));
				}
			}

			$i = $this->ctx->mm->getModel("Item", "m");
			$item = $i->getItem($item_oid);

			// коммент на итем и коммент на коммент имеют openid автора комментируемой записи
			if (isset($item->data['posted_by_id'])) {
				$rs = $m_oi->get_openid_for_user_by_oid($item->data['posted_by_id']);
				if ($rs)
				while ($openid = $rs->next()) {
					if ($is_on_item) {
						// теперь добавим второе событие - создание коммента на итем
						$this->ctx->logger->event(new Event(time(), "create_comment_at_item", $openid['openid'], $obj->id));
					} else {
						// теперь добавим второе событие - создание коммента на коммент
						$this->ctx->logger->event(new Event(time(), "create_comment_at_comment", $openid['openid'], $obj->id));
					}

				}
			}

			if ( $this->ctx->rh->use_search && $this->ctx->rh->search_in_comments ) {
				require_once 'includes/workaholic.php';
				Workaholic::addTask(array($this, 'hashItem'), $obj->id);
			}

			$this->ctx->logger->flushLog();

			return $obj;
		} else return false;


	}

	private function commentHtmlCleaner( $html ) {
		define('XML_HTMLSAX3', "safehtml/classes/");
		$this->rh->UseClass("safehtml_classes_safehtml");

		$safehtml =& new safehtml();
		return $safehtml->parse($html);
	}

	private function process_comment($comment_obj) {
		$m_user = $this->ctx->mm->getModel("User", "m");

		$_cm = $comment_obj->data;
		$_cm['oid'] = $comment_obj->id;
		$_cm['is_deleted'] = $comment_obj->is_deleted;

		$user = $m_user->getUser( $_cm['posted_by_id'] );

		$_cm['fullname'] = $user->data['fullname'];
		$_cm['avatar'] = $user->data['avatar'];
		$_cm['ctime'] = RL_CyrDate::newFromStr("%Y-%m-%d %H:%i:%s", $comment_obj->ctime);

		// проверим были ли изменения?
		if ($_cm['edited_user_oid'] > 0) {
			$edited_user = $m_user->getUser( $_cm['edited_user_oid'] );
			$_cm['edited_user'] = $edited_user->data;
			$_cm['edited_rlcd'] = RL_CyrDate::newFromStr("%Y-%m-%d %H:%i:%s", $_cm['edited_dtime']);
		}
		$_cm['acl'] = $this->aa->getAcl($comment_obj->id);


		$_cm['offset']--;
		return $_cm;
	}

	protected function init() {
		$this->aa = $this->module->aa;
		$this->ctx->mm->setAclAssistant( $this->aa );

		$this->rh->UseClass('RL_CyrDate');
		$this->m_comment = $this->ctx->mm->getModel("Comment", "m");
		$this->m_tc = $this->ctx->mm->getModel("TreeComments", "m");
	}

	public function hashItem( $oid ) {
		$this->rh->useClass('Search_Types');
		$searchTypes = new Search_Types($this->rh, $this->ctx->store);

		$data = $this->ctx->store->getObject($oid);

		$parser = $searchTypes->getTypeParser($data->type);
		if ( false === $parser ) {
			print "Can`t find parser for '{$data->type}' type.\n";
			return;
		}

		$parser->linkToObject($data->id);

		if ( $deleteItem ) {
			$parser->deleteItem($data->id);
		} else {
			$maked = $parser->makeSearchData($data->id);
			if ( !$maked ) {
				print "Can`t index item with '{$data->id}' oid.";
				return;
			}
		}

		$parser->cleanWords();
	}

	public function deleteItem( $oid ) {
		$this->rh->useClass('Search_Types');
		$searchTypes = new Search_Types($this->rh, $this->ctx->store);

		$data = $this->ctx->store->getObject($oid);

		$parser = $searchTypes->getTypeParser($data->type);
		if ( false === $parser ) {
			print "Can`t find parser for '{$data->type}' type.\n";
			return;
		}

		$parser->deleteItem($data->id);

		$parser->cleanWords();
	}
}
